home *** CD-ROM | disk | FTP | other *** search
/ Programming a Multiplayer FPS in DirectX / Programming a Multiplayer FPS in DirectX (Companion CD).iso / DirectX / dxsdk_oct2004.exe / dxsdk.exe / Samples / Managed / AudioVideo / Texture / texture.cs next >
Encoding:
Text File  |  2004-09-27  |  14.5 KB  |  309 lines

  1. //-----------------------------------------------------------------------------
  2. // File: texture.cs
  3. //
  4. // Copyright (c) Microsoft Corporation. All rights reserved.
  5. //-----------------------------------------------------------------------------
  6. using System;
  7. using System.Drawing;
  8. using System.Windows.Forms;
  9. using Microsoft.DirectX;
  10. using Microsoft.DirectX.Direct3D;
  11. using Microsoft.DirectX.AudioVideoPlayback;
  12. using Direct3D=Microsoft.DirectX.Direct3D;
  13. using Microsoft.Samples.DirectX.UtilityToolkit;
  14.  
  15. namespace VideoTextureSample
  16. {
  17.     public class VideoTexture : IDeviceCreation 
  18.     {
  19.         #region Creation
  20.         /// <summary>Create a new instance of the class</summary>
  21.         public VideoTexture(Framework f) 
  22.         { 
  23.             // Store framework
  24.             sampleFramework = f; 
  25.         }
  26.         #endregion
  27.  
  28.         private Framework sampleFramework = null; // Framework for samples
  29.         // Vertex buffer to hold the data for the geometry
  30.         private VertexBuffer vertexBuffer = null;
  31.         // The actual video itself
  32.         private Video videoTexture = null;
  33.         // Can the video be rendered?
  34.         private bool canRender = false;
  35.  
  36.         /// <summary>
  37.         /// Called during device initialization, this code checks the device for some 
  38.         /// minimum set of capabilities, and rejects those that don't pass by returning false.
  39.         /// </summary>
  40.         public bool IsDeviceAcceptable(Caps caps, Format adapterFormat, Format backBufferFormat, bool windowed)
  41.         {
  42.             // Any device is good
  43.             return true;
  44.         }
  45.  
  46.         /// <summary>
  47.         /// This callback function is called immediately before a device is created to allow the 
  48.         /// application to modify the device settings. The supplied settings parameter 
  49.         /// contains the settings that the framework has selected for the new device, and the 
  50.         /// application can make any desired changes directly to this structure.  Note however that 
  51.         /// the sample framework will not correct invalid device settings so care must be taken 
  52.         /// to return valid device settings, otherwise creating the Device will fail.  
  53.         /// </summary>
  54.         public void ModifyDeviceSettings(DeviceSettings settings, Caps caps)
  55.         {
  56.             // This application is designed to work on a pure device by not using 
  57.             // any get methods, so create a pure device if supported and using HWVP.
  58.             if ( (caps.DeviceCaps.SupportsPureDevice) && 
  59.                 ((settings.BehaviorFlags & CreateFlags.HardwareVertexProcessing) != 0 ) )
  60.                 settings.BehaviorFlags |= CreateFlags.PureDevice;
  61.  
  62.             // We will be using multiple threads
  63.             settings.presentParams.ForceNoMultiThreadedFlag = false;
  64.             settings.BehaviorFlags |= CreateFlags.MultiThreaded;
  65.         }
  66.  
  67.         
  68.         /// <summary>
  69.         /// This event will be fired immediately after the Direct3D device has been 
  70.         /// reset, which will happen after a lost device scenario. This is the best location to 
  71.         /// create Pool.Default resources since these resources need to be reloaded whenever 
  72.         /// the device is lost. Resources created here should be released in the OnLostDevice 
  73.         /// event. 
  74.         /// </summary>
  75.         public void OnResetDevice(object sender, DeviceEventArgs e)
  76.         {
  77.             // Now Create the VB
  78.             vertexBuffer = new VertexBuffer(typeof(CustomVertex.PositionNormalTextured), 100, 
  79.                 e.Device, Usage.WriteOnly, CustomVertex.PositionNormalTextured.Format, Pool.Default);
  80.             OnCreateVertexBuffer();
  81.  
  82.             // Set up our view matrix. A view matrix can be defined given an eye point,
  83.             // a point to lookat, and a direction for which way is up. Here, we set the
  84.             // eye five units back along the z-axis and up three units, look at the
  85.             // origin, and define "up" to be in the y-direction.
  86.             e.Device.Transform.View = Matrix.LookAtLH( new Vector3( 0.0f, 3.0f,-5.0f ), 
  87.                 new Vector3( 0.0f, 0.0f, 0.0f ), new Vector3( 0.0f, 1.0f, 0.0f ) );
  88.  
  89.             // For the projection matrix, we set up a perspective transform (which
  90.             // transforms geometry from 3D view space to 2D viewport space, with
  91.             // a perspective divide making objects smaller in the distance). To build
  92.             // a perpsective transform, we need the field of view (1/4 pi is common),
  93.             // the aspect ratio, and the near and far clipping planes (which define at
  94.             // what distances geometry should be no longer be rendered).
  95.             e.Device.Transform.Projection = Matrix.PerspectiveFovLH( (float)Math.PI / 4.0f, 1.0f, 1.0f, 100.0f );
  96.  
  97.             // Setup the ambient color
  98.             e.Device.RenderState.AmbientColor = unchecked((int)0xffffffff);
  99.             // Turn off culling, so we see the front and back of the triangle
  100.             e.Device.RenderState.CullMode = Cull.None;
  101.             // Turn off D3D lighting
  102.             e.Device.RenderState.Lighting = false;
  103.             // Turn on the ZBuffer
  104.             e.Device.RenderState.ZBufferEnable = true;
  105.  
  106.             e.Device.SamplerState[0].AddressU = TextureAddress.Clamp;
  107.             e.Device.SamplerState[0].AddressV = TextureAddress.Clamp;
  108.  
  109.             string path = Utility.FindMediaFile("video\\skiing.avi");
  110.  
  111.             try
  112.             {
  113.                 videoTexture = Video.FromFile(path);
  114.                 videoTexture.Ending += new System.EventHandler(this.MovieOver);
  115.                 videoTexture.TextureReadyToRender += new TextureRenderEventHandler(this.RenderIt);
  116.  
  117.                 // Now start rendering to our texture
  118.                 videoTexture.RenderToTexture(e.Device);
  119.  
  120.                 canRender = true;
  121.             }
  122.             catch(Exception err)
  123.             {
  124.                 MessageBox.Show(string.Format("An error has occurred that will not allow this sample to continue.\r\nException={0}", err.ToString()), "This sample must exit.", MessageBoxButtons.OK, MessageBoxIcon.Information);
  125.                 sampleFramework.CloseWindow();
  126.                 throw err;
  127.             }
  128.         }
  129.  
  130.         /// <summary>
  131.         /// This event function will be called fired after the Direct3D device has 
  132.         /// entered a lost state and before Device.Reset() is called. Resources created
  133.         /// in the OnResetDevice callback should be released here, which generally includes all 
  134.         /// Pool.Default resources. See the "Lost Devices" section of the documentation for 
  135.         /// information about lost devices.
  136.         /// </summary>
  137.         private void OnLostDevice(object sender, EventArgs e)
  138.         {
  139.             lock(this)
  140.             {
  141.                 try
  142.                 {
  143.                     canRender = false;
  144.                     if (vertexBuffer != null)
  145.                         vertexBuffer.Dispose();
  146.  
  147.                     vertexBuffer = null;
  148.  
  149.                     if (videoTexture != null)
  150.                         videoTexture.Dispose();
  151.  
  152.                     videoTexture = null;
  153.                 }
  154.                 catch{}
  155.             }
  156.         }
  157.  
  158.         /// <summary>
  159.         /// This event will be fired immediately after the Direct3D device has 
  160.         /// been destroyed, which generally happens as a result of application termination or 
  161.         /// windowed/full screen toggles. Resources created in the OnCreateDevice event 
  162.         /// should be released here, which generally includes all Pool.Managed resources. 
  163.         /// </summary>
  164.         private void OnDestroyDevice(object sender, EventArgs e)
  165.         {
  166.             lock(this)
  167.             {
  168.                 canRender = false;
  169.             }
  170.         }
  171.  
  172.  
  173.         /// <summary>
  174.         /// Fired when the video has a frame ready to be rendered into the texture
  175.         /// </summary>
  176.         void RenderIt(object sender, TextureRenderEventArgs e)
  177.         {
  178.             lock(this)
  179.             {
  180.                 Device device = sampleFramework.Device;
  181.                 // We will be updating the texture now
  182.                 using(e.Texture)
  183.                 {
  184.                     if (!canRender)
  185.                         return; // Cannot render right now
  186.  
  187.                     bool beginSceneCalled = false;
  188.                     // Clear the render target and the zbuffer 
  189.                     device.Clear(ClearFlags.ZBuffer | ClearFlags.Target, 0x000000ff, 1.0f, 0);
  190.  
  191.                     try
  192.                     {
  193.                         device.BeginScene();
  194.                         beginSceneCalled = true;
  195.  
  196.                         // Make sure this isn't being updated at this time
  197.                         // Setup the world matrix
  198.                         device.Transform.World = Matrix.RotationAxis(new Vector3((float)Math.Cos(Environment.TickCount / 250.0f),1,(float)Math.Sin(Environment.TickCount / 250.0f)), Environment.TickCount / 1000.0f );
  199.  
  200.                         // Set the texture
  201.                         device.SetTexture(0,e.Texture);
  202.                         device.SetStreamSource(0, vertexBuffer, 0);
  203.                         device.VertexFormat = CustomVertex.PositionNormalTextured.Format;
  204.                         device.DrawPrimitives(PrimitiveType.TriangleStrip, 0, (4*25)-2);
  205.                     }
  206.                     finally
  207.                     {
  208.                         if (beginSceneCalled)
  209.                             device.EndScene();
  210.                     }
  211.  
  212.                     device.Present();
  213.                 }
  214.             }
  215.         }
  216.         void MovieOver(object sender, EventArgs e)
  217.         {
  218.             videoTexture.Stop();
  219.             videoTexture.Play();
  220.         }
  221.         void OnCreateVertexBuffer()
  222.         {
  223.             // Create a vertex buffer (100 customervertex)
  224.             CustomVertex.PositionNormalTextured[] verts = (CustomVertex.PositionNormalTextured[])vertexBuffer.Lock(0,0); // Lock the buffer (which will return our structs)
  225.             for (int i = 0; i < 50; i++)
  226.             {
  227.                 // Fill up our structs
  228.                 float theta = (float)(2 * Math.PI * i) / 49;
  229.                 verts[2 * i].Position = new Vector3((float)Math.Sin(theta), -1, (float)Math.Cos(theta));
  230.                 verts[2 * i].Normal = new Vector3((float)Math.Sin(theta), 0, (float)Math.Cos(theta));
  231.                 verts[2 * i].Tu       = ((float)i)/(50-1);
  232.                 verts[2 * i].Tv       = 1.0f;
  233.                 verts[2 * i + 1].Position = new Vector3((float)Math.Sin(theta), 1, (float)Math.Cos(theta));
  234.                 verts[2 * i + 1].Normal = new Vector3((float)Math.Sin(theta), 0, (float)Math.Cos(theta));
  235.                 verts[2 * i + 1].Tu       = ((float)i)/(50-1);
  236.                 verts[2 * i + 1].Tv       = 0.0f;
  237.             }
  238.             // Unlock (and copy) the data
  239.             vertexBuffer.Unlock();
  240.         }
  241.  
  242.         /// <summary>
  243.         /// Entry point to the program. Initializes everything and goes into a message processing 
  244.         /// loop. Idle time is used to render the scene.
  245.         /// </summary>
  246.         static int Main() 
  247.         {
  248.             using(Framework sampleFramework = new Framework())
  249.             {
  250.                 VideoTexture sample = new VideoTexture(sampleFramework);
  251.                 // Set the callback functions. These functions allow the sample framework to notify
  252.                 // the application about device changes, user input, and windows messages.  The 
  253.                 // callbacks are optional so you need only set callbacks for events you're interested 
  254.                 // in. However, if you don't handle the device reset/lost callbacks then the sample 
  255.                 // framework won't be able to reset your device since the application must first 
  256.                 // release all device resources before resetting.  Likewise, if you don't handle the 
  257.                 // device created/destroyed callbacks then the sample framework won't be able to 
  258.                 // recreate your device resources.
  259.                 sampleFramework.Disposing += new EventHandler(sample.OnDestroyDevice);
  260.                 sampleFramework.DeviceLost += new EventHandler(sample.OnLostDevice);
  261.                 sampleFramework.DeviceReset += new DeviceEventHandler(sample.OnResetDevice);
  262.  
  263.                 try
  264.                 {
  265.  
  266.                     // Show the cursor and clip it when in full screen
  267.                     sampleFramework.SetCursorSettings(true, true);
  268.  
  269.                     // Initialize the sample framework and create the desired window and Direct3D 
  270.                     // device for the application. Calling each of these functions is optional, but they
  271.                     // allow you to set several options which control the behavior of the sampleFramework.
  272.                     sampleFramework.Initialize( true, false, true ); // Parse the command line, handle the default hotkeys, and show msgboxes
  273.                     sampleFramework.CreateWindow("VideoTexture");
  274.                     sampleFramework.CreateDevice( 0, true, Framework.DefaultSizeWidth, Framework.DefaultSizeHeight, 
  275.                         sample);
  276.  
  277.                     // Ignore size changes
  278.                     sampleFramework.IsIgnoringSizeChanges = true;
  279.                     // Pause rendering since it will be done when the texture is ready
  280.                     sampleFramework.Pause(false, true); 
  281.  
  282.                     // Pass control to the sample framework for handling the message pump and 
  283.                     // dispatching render calls. The sample framework will call your FrameMove 
  284.                     // and FrameRender callback when there is idle time between handling window messages.
  285.                     sampleFramework.MainLoop();
  286.  
  287.                 }
  288. #if(DEBUG)
  289.                 catch (Exception e)
  290.                 {
  291.                     // In debug mode show this error (maybe - depending on settings)
  292.                     sampleFramework.DisplayErrorMessage(e);
  293. #else
  294.             catch
  295.             {
  296.                 // In release mode fail silently
  297. #endif
  298.                     // Ignore any exceptions here, they would have been handled by other areas
  299.                     return (sampleFramework.ExitCode == 0) ? 1 : sampleFramework.ExitCode; // Return an error code here
  300.                 }
  301.  
  302.                 // Perform any application-level cleanup here. Direct3D device resources are released within the
  303.                 // appropriate callback functions and therefore don't require any cleanup code here.
  304.                 return sampleFramework.ExitCode;
  305.             }
  306.         }
  307.     }
  308. }
  309.